package com.chaucer.dynamicdemo.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @Description TODO
 * @Author Chaucer
 * @Date 2021/9/4 1:20
 */
@Component
@Aspect
@Slf4j
public class DataSourceAspect {
//    //切入点在service层的方法上，配置aop的切入点
//    @Pointcut("execution( * com.chaucer.dynamicdemo.service..*.*(..))")
//    public void dataSourcePointCut() {
//    }

    @Before("@annotation(DataSource)")
    public void before(JoinPoint joinPoint) {
        Object target = joinPoint.getTarget();
        String method = joinPoint.getSignature().getName();
        Class<?> className = joinPoint.getTarget().getClass();
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        try {
            Method m = className.getMethod(method, parameterTypes);
            //如果方法上存在切换数据源的注解，则根据注解内容进行数据源切换
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource annotation = m.getAnnotation(DataSource.class);
                String dataSourceName = annotation.value();
                DynamicThreadLocal.set(dataSourceName);
                log.debug("-----current thread " + Thread.currentThread().getName() + " add " + dataSourceName + " to ThreadLocal-----");

            } else {
                log.debug("switch datasource fail, use default");
            }
        } catch (NoSuchMethodException e) {
            log.error("current thread " + Thread.currentThread().getName() + " add data to ThreadLocal error", e);
        }
    }


    //执行完切面后，清空线程共享中的数据源名称
    @After("@annotation(DataSource)")
    public void after(JoinPoint joinPoint){
        DynamicThreadLocal.clearThreadLocal();
    }

}